package com.neusmart.tongrentang.dataLoadRequest;

import android.content.Intent;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.StringRequest;
import com.baidu.mobstat.StatService;
import com.neusmart.common.activity.BaseActivity;
import com.neusmart.common.dialog.OnNewClickListener;
import com.neusmart.common.util.L;
import com.neusmart.common.util.NetworkUtil;
import com.neusmart.tongrentang.F;
import com.neusmart.tongrentang.R;
import com.neusmart.tongrentang.activity.LoginActivity;
import com.neusmart.tongrentang.constants.API;
import com.neusmart.tongrentang.constants.RequestCode;
import com.neusmart.tongrentang.dialog.CustomAlertDialog;
import com.neusmart.tongrentang.model.AuthTokenInvalidEvent;
import com.neusmart.tongrentang.model.MParam;
import com.neusmart.tongrentang.result.Result;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.util.Map;

import de.greenrobot.event.EventBus;

/**
 * data load activity
 * <p/>
 * roy
 */

public abstract class DataLoadActivity extends BaseActivity {

    private static final String TAG = "ServerApi";

    protected static final int TAKE_COUNT = 10;

    public static String toJson(Object src) {
        return F.toJson(src);
    }

    public static <T> T fromJson(String json, Class<T> classOfT) {
        return F.fromJson(json, classOfT);
    }

    public static void putString(String key, String value) {
        F.putString(key, value);
    }

    public static String getString(String key, String defValue) {
        return F.getString(key, defValue);
    }

    public static void putBoolean(String key, boolean value) {
        F.putBoolean(key, value);
    }

    public static boolean getBoolean(String key, boolean defValue) {
        return F.getBoolean(key, defValue);
    }

    public static <T> T fromJson(String json, Type typeOfT) {
        return F.fromJson(json, typeOfT);
    }

    //子类调用此方法请求
    protected void loadData(API api, boolean loadHint) {
        if (!NetworkUtil.isNetworkConnected(this)) {
            showNetworkConnection(false);
            disposeResult(api, null, false);
            return;
        }
        if (loadHint)
            showProgressHUD();
        StatService.onEvent(DataLoadActivity.this.getApplicationContext(), "callAPI", api.toString(), 1);
        initParams(api, loadHint);
    }

    private void initParams(API api, boolean loadHint) {
        MParam param = new MParam(api, loadHint);
        initParams(param);
    }

    //子类重写此方法，设置相应参数
    protected void initParams(MParam param) {
        //
    }

    //子类在dataLoad(MParam param)中调用此方法
    protected void loadData(MParam param) {
        switch (param.getApi().getHttpMethod()) {
            case GET://
                volleyGet(param);
                break;
            case POST://NOT USED
                volleyPost(param);
                break;
            case POST_JSON://
                volleyPostJson(param);
                break;
            default:
                break;
        }
    }

    private void volleyGet(final MParam param) {
        L.d(TAG, "Get-Request:" + param.getRequestUrl());
        StringRequest request = new StringRequest(Request.Method.GET,
                param.getRequestUrl(), new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                // response
                L.d(TAG, "Response: " + response.toString());
                disposeResult(param.getApi(), response, param.isLoadHint());
            }

        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                // error
                showToast(R.string.request_failed);
                disposeResult(param.getApi(), null, param.isLoadHint());
            }

        }) {

            @Override
            protected Response<String> parseNetworkResponse(NetworkResponse response) {
                String str = null;
                try {
                    str = new String(response.data, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return Response.success(str, HttpHeaderParser.parseCacheHeaders(response));
            }

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                return F.headers;
            }

        };
        F.addRequest(request);
    }

    private void volleyPost(final MParam param) {
        L.d(TAG, "Post-Request:" + param.getRequestUrl());
        StringRequest request = new StringRequest(Request.Method.POST,
                param.getRequestUrl(), new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                // response
                L.d(TAG, "Response: " + response.toString());
                disposeResult(param.getApi(), response, param.isLoadHint());
            }

        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                // error
                showToast(R.string.request_failed);
                disposeResult(param.getApi(), null, param.isLoadHint());
            }

        }) {

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                return F.headers;
            }

            @Override
            protected Response<String> parseNetworkResponse(NetworkResponse response) {
                String str = null;
                try {
                    str = new String(response.data, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return Response.success(str, HttpHeaderParser.parseCacheHeaders(response));
            }

        };
        F.addRequest(request);
    }

    private void volleyPostJson(final MParam param) {
        L.d(TAG, "Post-JSON-Request:" + param.getRequestUrl() + ",params:" + param.getParams().toString());
        JsonObjectRequest request = null;
        try {
            request = new JsonObjectRequest(param.getRequestUrl(),
                    new JSONObject(toJson(param.getParams())), new Response.Listener<JSONObject>() {

                @Override
                public void onResponse(JSONObject response) {
                    // response
                    L.d(TAG, response.toString());
                    disposeResult(param.getApi(), response.toString(), param.isLoadHint());
                }

            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError arg0) {
                    // error
                    showToast(R.string.request_failed);
                    disposeResult(param.getApi(), null, param.isLoadHint());
                }

            }) {

                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    return F.headers;
                }

            };
        } catch (JSONException e) {
            e.printStackTrace();
        }
        if (request != null)
            F.addRequest(request);
    }

    private void disposeResult(API api, String response, boolean loadHint) {
        dismissProgressHUD();
        if (response == null) {
            disposeResult(api, response);
        } else {
            try {
                Result result = fromJson(response, Result.class);
                if (result.isAuthTokenInvalid()) {
                    F.logout();
                    showReLoginDialog();
                    return;
                }
                disposeResult(api, response);
            } catch (Exception e) {
                showToast(R.string.process_data_error);
                e.printStackTrace();
            }
        }
    }

    protected void disposeResult(API api, String response) {
        //
    }

    private void showReLoginDialog() {
        CustomAlertDialog dialog = new CustomAlertDialog(this);
        dialog.setLeftButton(R.string.cancel);
        dialog.setRightButton(R.string.re_login);
        TextView textView = new TextView(this);
        textView.setGravity(Gravity.CENTER);
        textView.setTextSize(16);
        textView.setText(R.string.auth_token_invalid);
        textView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        dialog.addContentView(textView);
        dialog.setOnNewClickListener(new OnNewClickListener() {
            @Override
            public void onLeftClick() {
                finish();
                EventBus.getDefault().post(new AuthTokenInvalidEvent());
            }

            @Override
            public void onRightClick() {
                switchActivityForResult(LoginActivity.class, RequestCode.AUTH_TOKEN_VALID_LOGIN, null);
            }
        });
        dialog.show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == RequestCode.AUTH_TOKEN_VALID_LOGIN) {
            if (resultCode == RESULT_OK)
                onReLoginSucceed();
            else
                onReLoginCanceled();
        }
    }

    protected void onReLoginSucceed() {
        onRefreshContent();
    }

    protected void onReLoginCanceled() {
        finish();
    }

}
